package cdu.sl.service.impl;

import cdu.sl.annotation.AutoFill;
import cdu.sl.common.enums.OperationType;
import cdu.sl.common.utils.BaseContext;
import cdu.sl.domain.dto.*;
import cdu.sl.domain.po.*;
import cdu.sl.domain.vo.FlashcardVO;
import cdu.sl.domain.vo.StudySetVO;
import cdu.sl.exception.BusinessException;
import cdu.sl.mapper.*;
import cdu.sl.service.StudySetService;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 学习集服务实现类
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class StudySetServiceImpl extends ServiceImpl<StudySetMapper, StudySet> implements StudySetService {

    private final StudySetMapper studySetMapper;
    private final FlashcardMapper flashcardMapper;
    private final UserMapper userMapper;
    private final UserStudySetsRecordsMapper userStudySetsRecordsMapper;
    private final CardStudyRecordMapper cardStudyRecordMapper;

    /**
     * 创建学习集
     *
     * @param dto 创建学习集DTO
     * @return 创建的学习集
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public StudySetVO createStudySet(StudySetCreateDTO dto) {
        Long userId = BaseContext.getCurrentId();
        // 1. 检查用户是否存在
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }

        // 2. 创建学习集
        StudySet studySet = new StudySet();
        BeanUtils.copyProperties(dto, studySet);
        studySet.setCreatorId(userId);
        studySet.setCardCount(dto.getFlashcards().size());
        studySet.setProgress(0);
        studySet.setLastAccessTime(LocalDateTime.now());
        studySet.setIsFeatured(false);

        // 设置默认值
        if (studySet.getIsPublic() == null) {
            studySet.setIsPublic(true);
        }
        if (studySet.getVisibility() == null) {
            studySet.setVisibility(0); // 可见程度 - 默认公开
        }

        studySetMapper.insert(studySet);
        // 更新tb_user_study_sets_records
        updateAccessTime(studySet.getId());

        // 3. 创建闪存卡
        List<Flashcard> flashcards = new ArrayList<>();
        int sortOrder = 0;
        for (FlashcardCreateDTO cardDto : dto.getFlashcards()) {
            Flashcard flashcard = new Flashcard();
            BeanUtils.copyProperties(cardDto, flashcard);
            flashcard.setStudySetId(studySet.getId());

            flashcard.setIsStarred(false);
            flashcard.setLearningStatus(0); // 未学习

            // 设置排序序号
            if (flashcard.getSortOrder() == null) {
                flashcard.setSortOrder(sortOrder++);
            } else {
                sortOrder = flashcard.getSortOrder() + 1;
            }

            flashcardMapper.insert(flashcard);
            flashcards.add(flashcard);
        }

        // 4. 构建返回结果
        return buildStudySetVO(studySet, flashcards, user);
    }

    /**
     * 根据ID获取学习集详情
     *
     * @param id 学习集ID
     * @return 学习集详情
     */
    @Override
    public StudySetVO getStudySetById(Long id) {
        // 1. 查询学习集
        StudySet studySet = studySetMapper.selectById(id);
        if (studySet == null) {
            throw new BusinessException("学习集不存在");
        }

        // 2. 查询创建者
        User creator = userMapper.selectById(studySet.getCreatorId());
        if (creator == null) {
            throw new BusinessException("创建者不存在");
        }

        // 3. 查询闪存卡列表
        List<Flashcard> flashcards = flashcardMapper.selectByStudySetId(studySet.getId());

        // 4. 只要根据id获取了学习集详情 , 就更新这个时间
        updateAccessTime(id);

        // 5. 构建返回结果
        return buildStudySetVO(studySet, flashcards, creator);
    }

    /**
     * 更新学习集的访问时间
     *
     * @param id 学习集ID
     */
    @Override
    public void updateAccessTime(Long id) {
        Long userId = BaseContext.getCurrentId();
        StudySet studySet = studySetMapper.selectById(id);

        QueryWrapper<UserStudySetsRecords> queryWrapper = new QueryWrapper<UserStudySetsRecords>().eq("user_id", userId).eq("study_set_id", id);
        UserStudySetsRecords userStudySetsRecords = userStudySetsRecordsMapper.selectOne(queryWrapper);
        log.info("查询到用户信息：{}", userStudySetsRecords);


        if (userStudySetsRecords == null) {
            // 如果为空 表明是初次访问 插入数据
            UserStudySetsRecords records = new UserStudySetsRecords();

            // 对必要字段赋值
            records.setUserId(userId);
            records.setStudySetId(id);
            // 这里如果要采用属性拷贝 ，需要将studySet id置为空 , 避免引发歧义
            studySet.setId(null);
            BeanUtil.copyProperties(studySet, records);
            records.setLastAccessTime(LocalDateTime.now());
            userStudySetsRecordsMapper.insert(records);
            return;
        }

        // 不为空 执行更新操作 只对last_access_time字段进行更新
        userStudySetsRecords.setLastAccessTime(LocalDateTime.now());
        userStudySetsRecordsMapper.updateById(userStudySetsRecords);

    }

    /**
     * 获取当前用户访问过的所有学习集
     * 前端可以根据lastAccessTime自行判断过滤
     *
     * @return 学习集列表
     */
    @Override
    public List<StudySetVO> getAllAccessedStudySets() {
        Long userId = BaseContext.getCurrentId();

        // 构建查询条件 - 查询当前用户访问过的所有学习集
        QueryWrapper<UserStudySetsRecords> wrapper = new QueryWrapper<UserStudySetsRecords>().eq("user_id", userId);
        // 查询表记录
        List<UserStudySetsRecords> userStudySetsRecordsList = userStudySetsRecordsMapper.selectList(wrapper);


        return userStudySetsRecordsList.stream().map(userStudySetsRecord -> {
            StudySetVO studySetVO = new StudySetVO();
            // 查询创建者信息
            StudySet studySet = studySetMapper.selectById(userStudySetsRecord.getStudySetId());
            User creator = userMapper.selectById(studySet.getCreatorId());
            // 设置创建者信息
            studySetVO.setCreatorId(creator.getId());
            studySetVO.setCreatorAvatar(creator.getAvatar());
            studySetVO.setCreatorName(creator.getUsername());

            // 设置学习集基本信息
            BeanUtil.copyProperties(studySet, studySetVO);
            return studySetVO;
        }).collect(Collectors.toList());

//
//        // 构建返回结果 - 不立即加载闪存卡，减轻数据库负担
//        return studySets.stream().map(studySet -> {
//            StudySetVO vo = new StudySetVO();
//            BeanUtils.copyProperties(studySet, vo);
//
//            // 设置创建者信息
//            vo.setCreatorName(creator.getUsername());
//            vo.setCreatorAvatar(creator.getAvatar());
//            vo.setAccountType(creator.getAccountType());
//
//            // 不加载详细的闪存卡信息，只返回数量
//            vo.setFlashcards(null);
//
//            return vo;
//        }).collect(Collectors.toList());
    }


    /**
     * 修改学习集
     *
     * @param dto 修改学习集DTO
     * @return 修改后的学习集
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public StudySetVO updateStudySet(StudySetUpdateDTO dto) {
        Long userId = BaseContext.getCurrentId();

        // 1. 查询学习集是否存在
        StudySet studySet = studySetMapper.selectById(dto.getId());
        if (studySet == null) {
            throw new BusinessException("学习集不存在");
        }

        // 2. 检查权限，只有创建者可以修改
        if (!studySet.getCreatorId().equals(userId)) {
            throw new BusinessException("您没有权限修改此学习集");
        }

        // 3. 修改学习集基本信息
        BeanUtils.copyProperties(dto, studySet);
        studySet.setUpdatedAt(LocalDateTime.now());
        studySet.setCardCount(dto.getFlashcards().size());
        studySetMapper.updateById(studySet);

        // 4. 删除该学习集下所有闪存卡
        LambdaQueryWrapper<Flashcard> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Flashcard::getStudySetId, studySet.getId());
        flashcardMapper.delete(queryWrapper);

        // 5. 重新插入所有闪存卡
        List<Flashcard> flashcards = new ArrayList<>();
        int sortOrder = 0;

        for (FlashcardUpdateDTO cardDto : dto.getFlashcards()) {
            // 跳过标记为删除的卡片
            if (Boolean.TRUE.equals(cardDto.getIsDeleted())) {
                continue;
            }

            Flashcard flashcard = new Flashcard();
            BeanUtils.copyProperties(cardDto, flashcard);
            flashcard.setId(null); // 确保生成新的ID
            flashcard.setStudySetId(studySet.getId());
            flashcard.setIsStarred(false);
            flashcard.setLearningStatus(0); // 未学习

            // 设置排序序号
            if (flashcard.getSortOrder() == null) {
                flashcard.setSortOrder(sortOrder++);
            } else {
                sortOrder = flashcard.getSortOrder() + 1;
            }

            flashcardMapper.insert(flashcard);
            flashcards.add(flashcard);
        }

        // 6. 查询创建者
        User creator = userMapper.selectById(studySet.getCreatorId());

        // 7. 构建返回结果
        return buildStudySetVO(studySet, flashcards, creator);
    }

    /**
     * 删除学习集
     *
     * @param id 学习集ID
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteStudySet(Long id) {
        Long userId = BaseContext.getCurrentId();

        // 1. 查询学习集是否存在
        StudySet studySet = studySetMapper.selectById(id);
        if (studySet == null) {
            throw new BusinessException("学习集不存在");
        }

        // 2. 检查权限，只有创建者可以删除
        if (!studySet.getCreatorId().equals(userId)) {
            throw new BusinessException("您没有权限删除此学习集");
        }

        // 3. 删除该学习集下所有闪存卡
        LambdaQueryWrapper<Flashcard> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Flashcard::getStudySetId, id);
        flashcardMapper.delete(queryWrapper);

        // 4. 删除学习集
        studySetMapper.deleteById(id);
    }

    /**
     * 构建学习集VO
     */
    private StudySetVO buildStudySetVO(StudySet studySet, List<Flashcard> flashcards, User creator) {
        StudySetVO vo = new StudySetVO();
        BeanUtils.copyProperties(studySet, vo);

        // 设置创建者信息
        vo.setCreatorName(creator.getUsername());
        vo.setCreatorAvatar(creator.getAvatar());
        vo.setAccountType(creator.getAccountType());

        // 转换闪存卡列表
        List<FlashcardVO> flashcardVOs = flashcards.stream().map(flashcard -> {
            FlashcardVO flashcardVO = new FlashcardVO();
            BeanUtils.copyProperties(flashcard, flashcardVO);
            return flashcardVO;
        }).collect(Collectors.toList());

        vo.setFlashcards(flashcardVOs);
        return vo;
    }


    /**
     * 获取当前用户创建的学习集 只需基本信息
     *
     * @return 学习集视图模型
     */
    @Override
    public List<StudySetVO> getMyStudySets() {
        Long userId = BaseContext.getCurrentId();
        // 1.获得creator_id等于userId的学习集
        List<StudySet> studySetList = lambdaQuery().eq(StudySet::getCreatorId, userId).list();

        return studySetList.stream().map(studySet -> {
            StudySetVO studySetVO = new StudySetVO();

            // 构建学习集基本信息
            BeanUtil.copyProperties(studySet, studySetVO);

            // 填充创建者信息
            User creator = userMapper.selectById(userId);
            studySetVO.setCreatorName(creator.getUsername());
            studySetVO.setCreatorAvatar(creator.getAvatar());
            studySetVO.setCreatorId(creator.getId());

            return studySetVO;
        }).collect(Collectors.toList());
    }


    /**
     * 获取热门学习集列表
     *
     * @return 热门学习集列表
     */
    @Override
    public List<StudySetVO> getHotStudySets() {
        return userStudySetsRecordsMapper.selectHotStudySets();
    }

    /**
     * 更新单词卡学习进度
     *
     * @param cardStudyRecordDTO 更新单词卡数据传输对象
     */
    @Override
    public void progressChecking(CardStudyRecordDTO cardStudyRecordDTO) {
        Long userId = BaseContext.getCurrentId();
        Long flashCardId = cardStudyRecordDTO.getFlashcardId();
        LambdaQueryWrapper<CardStudyRecord> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(CardStudyRecord::getUserId, userId)
                  .eq(CardStudyRecord::getFlashcardId, flashCardId);
        CardStudyRecord cardStudyRecord = cardStudyRecordMapper.selectOne(queryWrapper);
        log.info("res:{}",cardStudyRecord);
        if(cardStudyRecord==null){
            // 初次开启进度跟踪 执行插入操作
            CardStudyRecord record = BeanUtil.copyProperties(cardStudyRecordDTO, CardStudyRecord.class);
            record.setUserId(userId);
            record.setStudyCount(1);
            record.setLastStudiedAt(LocalDateTime.now());
            record.setId(null);
            log.info("插入对象：{}",record);
            cardStudyRecordMapper.insert(record);
            return;
        }
        // 否则执行更新操作
        Integer learningStatus= cardStudyRecordDTO.getLearningStatus();
        cardStudyRecord.setLearningStatus(learningStatus);
        cardStudyRecord.setStudyCount(cardStudyRecord.getStudyCount() + 1);
        cardStudyRecord.setLastStudiedAt(LocalDateTime.now());
        cardStudyRecord.setLastStudiedAt(LocalDateTime.now());
        cardStudyRecordMapper.updateById(cardStudyRecord);
    }


}
